//------------------------------------------------------------
//  Filename: eth_mac_top.sv
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2020-11-28 14:41
//  Description: 
//   
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps

interface BDU_IF #( 
    parameter ADDR_WIDTH = 16, 
    parameter DATA_WIDTH = 32
);
    logic [ADDR_WIDTH-1:0] addr; 
    logic                  req; 
    logic                  gnt; 
    logic [DATA_WIDTH-1:0] wdata; 
    logic                  we; 
    logic [DATA_WIDTH-1:0] rdata; 
    logic                  rvalid; 
    
    modport Master ( 
        output req,addr,we,wdata, 
        input  rdata,rvalid,gnt 
    ); 

    modport Slave ( 
        input  req,addr,we,wdata, 
        output rdata,rvalid,gnt 
    ); 

endinterface 

module eth_mac_top ( 
    input  logic         sys_clk_i, 
    input  logic         sys_rstn_i, 

    input  logic[15:0]   cpu_mem_addr,
    input  logic         cpu_mem_req,
    output logic         cpu_mem_gnt,
    output logic[31:0]   cpu_mem_rdata,
    output logic         cpu_mem_rvalid,
    input  logic[31:0]   cpu_mem_wdata,
    input  logic         cpu_mem_we,

    output logic[15:0]   mrx_dma_addr,
    output logic         mrx_dma_req,
    input  logic         mrx_dma_gnt,
    input  logic[31:0]   mrx_dma_rdata,
    input  logic         mrx_dma_rvalid,
    output logic[31:0]   mrx_dma_wdata,
    output logic         mrx_dma_we,    

    output logic[15:0]   mtx_dma_addr,
    output logic         mtx_dma_req,
    input  logic         mtx_dma_gnt,
    input  logic[31:0]   mtx_dma_rdata,
    input  logic         mtx_dma_rvalid,
    output logic[31:0]   mtx_dma_wdata,
    output logic         mtx_dma_we,        
 
    input  logic         refclk,     // rmii interface
    input  logic[1:0]    rxd,
    input  logic         crsdv,
    output logic[1:0]    txd,
    output logic         tx_en
);    
//-------------------------------------------------------------
logic       tx_clk                            ;
logic[3:0]  tx_data                           ;
logic       tx_data_v                         ;

logic       rx_clk                            ;
logic[3:0]  rx_data                           ;
logic       rx_data_v                         ;

logic[7:0]  mac_rx_data                       ;  
logic       mac_rx_valid                      ;  
logic       mac_rx_sof                        ;  
logic       mac_rx_eof                        ;  
logic       mac_rx_err                        ;  

logic       dma_rx_en                         ;
logic       dma_rx_busy                       ;
logic[3:0]  dma_rx_err                        ;
logic[6:0]  dma_rx_rptr                       ;

logic       dma_tx_need                       ;
logic       dma_tx_en                         ;
logic       dma_tx_busy                       ;
logic[3:0]  dma_tx_err                        ;
logic[6:0]  dma_tx_rptr                       ;

logic[7:0]  mac_tx_data                       ;  
logic       mac_tx_valid                      ;  
logic       mac_tx_ready                      ;  
logic       mac_tx_eof                        ;  
logic[3:0]  mac_tx_ifg                        ;  

logic[9:0]  mac_sw_din                        ;   
logic[7:0]  mac_sw_data                       ;   
logic       mac_sw_valid                      ; 
logic       mac_sw_ready                      ; 
logic       mac_sw_eof                        ;   

logic[7:0]  mac_ft_data                       ;   
logic       mac_ft_valid                      ; 
logic       mac_ft_ready                      ; 
logic       mac_ft_sof                        ;   
logic       mac_ft_eof                        ;   
logic       mac_ft_err                        ; 
logic[9:0]  mac_ft_din                        ;

logic[9:0]  dma_rx_data                       ;
logic       dma_rx_valid                      ;
logic       dma_rx_ready                      ;

logic[9:0]  dma_tx_data                       ;
logic       dma_tx_valid                      ;
logic       dma_tx_ready                      ;

logic       mac_rx_strip                      ;
logic       mac_cfg_loop                      ;
logic       mac_cfg_byps                      ;
logic       mac_lp_ready                      ;
logic[47:0] mac_uni_addr                      ;
//-------------------------------------------------------------
BDU_IF      cpu_lint()                        ;
BDU_IF      mrx_lint()                        ;
BDU_IF      mtx_lint()                        ;
BDU_IF      cfg_lint()                        ;
BDU_IF      cpu_master[2]()                   ;
BDU_IF      bdu_lint[3]()                     ;
//-------------------------------------------------------------
eth_mac_cfgif 
eth_mac_cfgif_inst0
( 
    .clk_i           ( sys_clk_i        ) ,  
    .rstn_i          ( sys_rstn_i       ) ,  

    .cpu_lint        ( cpu_lint         ) ,
    .cpu_master      ( cpu_master       ) 
);
//-------------------------------------------------------------
eth_mac_rmii2mii
eth_mac_rmii2mii_inst0
( 
    .rstn_i          ( sys_rstn_i       ) ,
  
    .refclk          ( refclk           ) ,
    .rxd             ( rxd              ) ,  
    .crsdv           ( crsdv            ) ,
    .txd             ( txd              ) ,
    .tx_en           ( tx_en            ) ,

    .tx_clk          ( tx_clk           ) , 
    .tx_data         ( tx_data          ) , 
    .tx_data_v       ( tx_data_v        ) ,
                  
    .rx_clk          ( rx_clk           ) ,
    .rx_data         ( rx_data          ) , 
    .rx_data_v       ( rx_data_v        ) ,
         
    .phy_crs         (                  ) , 
    .phy_col         (                  ) 
);   
//-------------------------------------------------------------
eth_mac_rx
eth_mac_rx_inst0
( 
    .rstn_i          ( sys_rstn_i       ) ,

    .rx_clk          ( rx_clk           ) ,
    .rx_data         ( rx_data          ) ,   
    .rx_data_v       ( rx_data_v        ) ,  

    .mac_rx_chk_en   ( 1'b1             ) ,
    .mac_rx_drop_bcst( 1'b1             ) ,
    .mac_rx_drop_mcst( 1'b1             ) ,
    .mac_rx_pass_all ( 1'b1             ) ,
    .mac_rx_hash_tab ( 63'b0            ) , //multicast hash table
    
    .mac_uni_addr    ( 48'h01005e0000fb ) , //( mac_uni_addr     ) ,
    .mac_rx_data     ( mac_rx_data      ) ,
    .mac_rx_valid    ( mac_rx_valid     ) ,
    .mac_rx_sof      ( mac_rx_sof       ) ,
    .mac_rx_eof      ( mac_rx_eof       ) , 
    .mac_rx_err      ( mac_rx_err       ) ,

    .mac_ft_abort    ( mac_ft_abort     )
);
//-------------------------------------------------------------
assign mac_ft_din = {mac_ft_sof,mac_ft_eof,mac_ft_data};
//-------------------------------------------------------------
eth_mac_filter  
eth_mac_filter_inst0
( 
    .rstn_i          ( sys_rstn_i       ) , 
    .clk_i           ( rx_clk           ) ,

    .mac_rx_strip    ( mac_rx_strip     ) ,
    .mac_cfg_loop    ( mac_cfg_loop     ) ,
    .mac_lp_ready    ( mac_lp_ready     ) ,

    .mac_rx_data     ( mac_rx_data      ) ,
    .mac_rx_valid    ( mac_rx_valid     ) ,
    .mac_rx_sof      ( mac_rx_sof       ) ,
    .mac_rx_eof      ( mac_rx_eof       ) , 
    .mac_rx_err      ( mac_rx_err       ) ,

    .mac_ft_abort    ( mac_ft_abort     ) ,
    .mac_ft_data     ( mac_ft_data      ) ,
    .mac_ft_valid    ( mac_ft_valid     ) ,
    .mac_ft_ready    ( mac_ft_ready     ) ,
    .mac_ft_sof      ( mac_ft_sof       ) , 
    .mac_ft_eof      ( mac_ft_eof       ) , 
    .mac_ft_err      ( mac_ft_err       ) 
); 
//-------------------------------------------------------------
eth_mac_afifo #(
    .FIFO_WIDTH      ( 10               ) ,
    .FIFO_DEEPTH     ( 4                )
)
eth_mac_afifo_rx_inst0
( 
    .rstn_i          ( sys_rstn_i       ) ,  
   
    .wclk            ( rx_clk           ) ,  
    .wdata           ( mac_ft_din       ) ,
    .wvalid          ( mac_ft_valid     ) , 
    .wready          ( mac_ft_ready     ) , 

    .rclk            ( sys_clk_i        ) ,
    .rdata           ( dma_rx_data      ) ,
    .rvalid          ( dma_rx_valid     ) ,
    .rready          ( dma_rx_ready     )
);   
//-------------------------------------------------------------
eth_mac_rxdma 
eth_mac_rxdma_inst0
( 
    .clk_i           ( sys_clk_i        ) ,   
    .rstn_i          ( sys_rstn_i       ) ,  
 
    .dma_rx_data     ( dma_rx_data      ) ,
    .dma_rx_valid    ( dma_rx_valid     ) ,
    .dma_rx_ready    ( dma_rx_ready     ) ,

    .dma_rx_en       ( dma_rx_en        ) ,
    .dma_rx_busy     ( dma_rx_busy      ) ,
    .dma_rx_err      ( dma_rx_err       ) ,
    .dma_rx_rptr     ( dma_rx_rptr      ) ,

    .mac_ft_err      ( mac_ft_err       ) ,

    .bdu_master      ( bdu_lint[1]      ) ,
    .mem_master      ( mrx_lint         ) 
);
//-------------------------------------------------------------
eth_mac_rf  #(
    .N_PORTS         ( 3                ) 
)
eth_mac_rf_inst0
(
    .clk_i           ( sys_clk_i        ) , 
    .rstn_i          ( sys_rstn_i       ) , 

    .mac_tx_ifg      ( mac_tx_ifg       ) ,
    .mac_rx_strip    ( mac_rx_strip     ) ,
    .mac_cfg_loop    ( mac_cfg_loop     ) ,
    .mac_cfg_byps    ( mac_cfg_byps     ) ,
    .mac_uni_addr    ( mac_uni_addr     ) ,

    .dma_rx_en       ( dma_rx_en        ) ,
    .dma_rx_busy     ( dma_rx_busy      ) ,
    .dma_rx_err      ( dma_rx_err       ) ,
    .dma_rx_rptr     ( dma_rx_rptr      ) ,

    .dma_tx_need     ( dma_tx_need      ) ,
    .dma_tx_en       ( dma_tx_en        ) ,
    .dma_tx_busy     ( dma_tx_busy      ) ,
    .dma_tx_err      ( dma_tx_err       ) ,
    .dma_tx_rptr     ( dma_tx_rptr      ) ,

    .cfg_slave       ( cfg_lint         ) ,
    .lint_slave      ( bdu_lint         )  
);
//-------------------------------------------------------------
eth_mac_txdma 
eth_mac_txdma_inst0
( 
    .clk_i           ( sys_clk_i        ) ,
    .rstn_i          ( sys_rstn_i       ) ,
 
    .mac_tx_ifg      ( mac_tx_ifg       ) ,

    .dma_tx_data     ( dma_tx_data      ) ,
    .dma_tx_valid    ( dma_tx_valid     ) ,
    .dma_tx_ready    ( dma_tx_ready     ) ,

    .dma_tx_need     ( dma_tx_need      ) ,
    .dma_tx_en       ( dma_tx_en        ) ,
    .dma_tx_busy     ( dma_tx_busy      ) ,
    .dma_tx_err      ( dma_tx_err       ) ,
    .dma_tx_rptr     ( dma_tx_rptr      ) ,

    .bdu_master      ( bdu_lint[2]      ) ,
    .mem_master      ( mtx_lint         )  
);
//-------------------------------------------------------------
eth_mac_afifo #(
    .FIFO_WIDTH      ( 10               ) ,
    .FIFO_DEEPTH     ( 4                ) ,
    .FIFO_VLD_OP     ( 0                ) 
)
eth_mac_afifo_tx_inst0
( 
    .rstn_i          ( sys_rstn_i       ) ,  
   
    .wclk            ( sys_clk_i        ) ,  
    .wdata           ( dma_tx_data      ) ,
    .wvalid          ( dma_tx_valid     ) ,
    .wready          ( dma_tx_ready     ) ,

    .rclk            ( tx_clk           ) ,
    .rdata           ( mac_sw_din       ) ,
    .rvalid          ( mac_sw_valid     ) , 
    .rready          ( mac_sw_ready     )
); 
//-------------------------------------------------------------
assign {mac_sw_sof,mac_sw_eof,mac_sw_data} = mac_sw_din[9:0];
//-------------------------------------------------------------
eth_mac_addswap #( 
    .DEEPTH          ( 16               ) 
) 
eth_mac_addswap_inst0
( 
    .rstn_i          ( sys_rstn_i       ) ,
                                        
    .clk_i           ( tx_clk           ), 
                                        
    .mac_cfg_loop    ( mac_cfg_loop     ) , 
    .mac_cfg_byps    ( mac_cfg_byps     ) , 
    .mac_uni_addr    ( mac_uni_addr     ) , 
                   
    .mac_ft_data     ( mac_ft_data      ) ,   
    .mac_ft_valid    ( mac_ft_valid     ) , 
    .mac_ft_sof      ( mac_ft_sof       ) ,   
    .mac_ft_eof      ( mac_ft_eof       ) ,   
    .mac_lp_ready    ( mac_lp_ready     ) ,  
                  
    .mac_sw_data     ( mac_sw_data      ) ,   
    .mac_sw_sof      ( mac_sw_sof       ) ,   
    .mac_sw_eof      ( mac_sw_eof       ) ,   
    .mac_sw_valid    ( mac_sw_valid     ) , 
    .mac_sw_ready    ( mac_sw_ready     ) , 
                   
    .mac_tx_data     ( mac_tx_data      ) ,   
    .mac_tx_eof      ( mac_tx_eof       ) ,   
    .mac_tx_valid    ( mac_tx_valid     ) , 
    .mac_tx_ready    ( mac_tx_ready     ) 
);
//-------------------------------------------------------------
eth_mac_tx
eth_mac_tx_inst0
( 
    .rstn_i          ( sys_rstn_i       ) ,

    .mac_cfg_fes     ( mac_cfg_fes      ) ,
                 
    .mac_tx_data     ( mac_tx_data      ) ,
    .mac_tx_valid    ( mac_tx_valid     ) ,
    .mac_tx_eof      ( mac_tx_eof       ) ,
    .mac_tx_ready    ( mac_tx_ready     ) ,

    .tx_clk          ( tx_clk           ) ,
    .tx_data         ( tx_data          ) ,   
    .tx_data_v       ( tx_data_v        )   
    
);
//-------------------------------------------------------------
assign mrx_dma_addr         = mrx_lint.addr       ;
assign mrx_dma_req          = mrx_lint.req        ;
assign mrx_dma_wdata        = mrx_lint.wdata      ;
assign mrx_dma_we           = mrx_lint.we         ; 

assign mrx_lint.gnt         = mrx_dma_gnt         ;
assign mrx_lint.rdata       = mrx_dma_rdata       ;
assign mrx_lint.rvalid      = mrx_dma_rvalid      ;

assign mtx_dma_addr         = mtx_lint.addr       ;
assign mtx_dma_req          = mtx_lint.req        ;
assign mtx_dma_wdata        = mtx_lint.wdata      ;
assign mtx_dma_we           = mtx_lint.we         ; 

assign mtx_lint.gnt         = mtx_dma_gnt         ;
assign mtx_lint.rdata       = mtx_dma_rdata       ;
assign mtx_lint.rvalid      = mtx_dma_rvalid      ;
//-------------------------------------------------------------
assign cpu_lint.addr        = cpu_mem_addr        ;
assign cpu_lint.req         = cpu_mem_req         ;
assign cpu_lint.wdata       = cpu_mem_wdata       ;
assign cpu_lint.we          = cpu_mem_we          ; 
                         
assign cpu_mem_gnt          = cpu_lint.gnt        ;
assign cpu_mem_rdata        = cpu_lint.rdata      ;
assign cpu_mem_rvalid       = cpu_lint.rvalid     ;
//-------------------------------------------------------------
assign cfg_lint.addr        = cpu_master[0].addr  ;
assign cfg_lint.req         = cpu_master[0].req   ;
assign cfg_lint.wdata       = cpu_master[0].wdata ;
assign cfg_lint.we          = cpu_master[0].we    ;
                         
assign cpu_master[0].gnt    = cfg_lint.gnt        ;
assign cpu_master[0].rdata  = cfg_lint.rdata      ;
assign cpu_master[0].rvalid = cfg_lint.rvalid     ;
//-------------------------------------------------------------
assign bdu_lint[0].addr     = cpu_master[1].addr  ;
assign bdu_lint[0].req      = cpu_master[1].req   ;
assign bdu_lint[0].wdata    = cpu_master[1].wdata ;
assign bdu_lint[0].we       = cpu_master[1].we    ;
                         
assign cpu_master[1].gnt    = bdu_lint[0].gnt     ;
assign cpu_master[1].rdata  = bdu_lint[0].rdata   ;
assign cpu_master[1].rvalid = bdu_lint[0].rvalid  ; 

endmodule
